package com.test;

import com.sun.jdi.*;
import com.sun.jdi.connect.AttachingConnector;
import com.sun.jdi.connect.Connector;
import com.sun.tools.jdi.SocketAttachingConnector;

import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Collections;
import java.io.FileWriter;
import java.io.Writer;
import java.io.IOException;
import java.io.OutputStreamWriter;

/**
 * Created by IntelliJ IDEA.
 * User: adenysenko
 * Date: Aug 12, 2005
 * Time: 11:15:27 AM
 * To change this template use File | Settings | File Templates.
 */
public class RunProfiler {
    //static final int PORT = 50121; // Netweaver
    //static final int PORT = 50121; // Weblogic
    static final String HOST="adenysenko";
    static final int PORT = 50121;
    static String outputFile="/tmp/frameStats.xml";
    private static final String FILTER_TEXT = "doPost";

    static volatile boolean stop=false;

    public static void main(String[] args) throws Exception{
        AttachingConnector sockAttach=null;
        for( AttachingConnector c : Bootstrap.virtualMachineManager().attachingConnectors()){
            if( c instanceof SocketAttachingConnector){
                sockAttach=c;
            }
        }
        Map<String, Connector.Argument> arg = sockAttach.defaultArguments();
        ((Connector.StringArgument)arg.get("hostname")).setValue(HOST);
        ((Connector.IntegerArgument)arg.get("port")).setValue(PORT);
        VirtualMachine vm = sockAttach.attach(arg);

        System.out.print("press enter to start>");
        System.in.read();

        new Thread(){
            @Override
            public void run() {
                try {
                    System.in.read();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                stop=true;
            }
        }.start();

        FrameStats stats = new FrameStats();
        for( int i=0; !stop; i++ ){
            System.out.print("\nsnapshot "+i+" ... press enter to stop");
            vm.suspend();
            try{
                //printThreads(vm);
                updateFrameOccurences(vm, stats);
            }
            finally{
              vm.resume();
            }
            Thread.sleep(500);
        }
        stats.print(new OutputStreamWriter(System.out));
        Writer w = new FileWriter(outputFile);
        stats.saveXML(w,FILTER_TEXT);
        w.close();
    }

    private static void printThreads(VirtualMachine vm) {
        List<ThreadReference> threads = vm.allThreads();
        for(ThreadReference tr : threads){
            System.out.println( tr.toString() /*tr.name()*/ );
        }
    }

    private static void updateFrameOccurences(
            VirtualMachine vm, FrameStats stats) {
        List<ThreadReference> threads = vm.allThreads();
        for(ThreadReference tr : threads){
            //System.out.println( tr.toString() /*tr.name()*/ );
            List<StackFrame> frames =  null;
            try {
                frames = tr.frames();
            } catch (IncompatibleThreadStateException e) {
                //e.printStackTrace(System.out);
                continue;
            }
            FrameStats nestedStats = stats;
            List<StackFrame> framesRev = new ArrayList<StackFrame>(frames);
            Collections.reverse(framesRev);
            for( StackFrame sf : framesRev ){
               String loc=sf.location().method().toString();
                nestedStats=nestedStats.recordNestedInvocation(loc);
               //System.out.println(  "  "+sf.location() );
            }
        }
    }
}
